package com.evan.review.anr;

import android.os.Bundle;
import android.os.SystemClock;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.ScrollView;
import android.widget.TextView;

import androidx.appcompat.app.AppCompatActivity;

import com.evan.review.R;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Random;

/**
 * 主线程阻塞ANR示例Activity
 * 演示不同类型的主线程阻塞导致的ANR
 */
public class MainThreadBlockActivity extends AppCompatActivity implements View.OnClickListener {

    private static final String TAG = "MainThreadBlockANR";
    
    private Button btnSleep; // 睡眠阻塞按钮
    private Button btnBusyLoop; // 死循环阻塞按钮
    private Button btnIOBlock; // IO阻塞按钮
    private Button btnComplexCalculation; // 复杂计算阻塞按钮
    private TextView tvLogger; // 日志文本框
    private ScrollView svLogger; // 日志滚动视图
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main_thread_block);
        
        initViews(); // 初始化视图
        setListeners(); // 设置监听器
        
        logMessage("提示：点击以下按钮将引发不同类型的ANR，请注意观察系统ANR对话框和日志输出");
        logMessage("ANR发生时间阈值：输入事件5秒、前台广播10秒、前台服务20秒");
    }
    
    /**
     * 初始化视图组件
     */
    private void initViews() {
        btnSleep = findViewById(R.id.btn_sleep);
        btnBusyLoop = findViewById(R.id.btn_busy_loop);
        btnIOBlock = findViewById(R.id.btn_io_block);
        btnComplexCalculation = findViewById(R.id.btn_complex_calculation);
        tvLogger = findViewById(R.id.tv_logger);
        svLogger = findViewById(R.id.sv_logger);
    }
    
    /**
     * 设置监听器
     */
    private void setListeners() {
        btnSleep.setOnClickListener(this);
        btnBusyLoop.setOnClickListener(this);
        btnIOBlock.setOnClickListener(this);
        btnComplexCalculation.setOnClickListener(this);
    }
    
    @Override
    public void onClick(View v) {
        int id = v.getId();
        
        if (id == R.id.btn_sleep) {
            logMessage("开始执行睡眠阻塞操作...");
            triggerSleepANR();
        } else if (id == R.id.btn_busy_loop) {
            logMessage("开始执行死循环阻塞操作...");
            triggerBusyLoopANR();
        } else if (id == R.id.btn_io_block) {
            logMessage("开始执行IO阻塞操作...");
            triggerIOBlockANR();
        } else if (id == R.id.btn_complex_calculation) {
            logMessage("开始执行复杂计算阻塞操作...");
            triggerComplexCalculationANR();
        }
    }
    
    /**
     * 引发睡眠阻塞导致的ANR
     * 直接在主线程中休眠10秒，超过系统ANR阈值
     */
    private void triggerSleepANR() {
        logMessage("主线程即将休眠10秒，这将导致ANR...");
        SystemClock.sleep(10000); // 睡眠10秒，确保超过ANR阈值
        logMessage("主线程休眠结束，如果看到此消息，说明ANR对话框被忽略或等待");
    }
    
    /**
     * 引发死循环阻塞导致的ANR
     * 在主线程中执行一个耗时的空循环
     */
    private void triggerBusyLoopANR() {
        logMessage("主线程即将执行一个耗时的死循环，这将导致ANR...");
        long startTime = System.currentTimeMillis();
        
        // 执行10秒的空循环
        while ((System.currentTimeMillis() - startTime) < 10000) {
            // 空循环，消耗CPU
            for (int i = 0; i < 1000000; i++) {
                // 空操作
            }
        }
        
        logMessage("死循环执行结束，如果看到此消息，说明ANR对话框被忽略或等待");
    }
    
    /**
     * 引发IO阻塞导致的ANR
     * 在主线程中执行大量文件IO操作
     */
    private void triggerIOBlockANR() {
        logMessage("主线程即将执行大量IO操作，这将导致ANR...");
        
        try {
            // 创建一个临时文件
            File tempFile = File.createTempFile("anr_test", ".txt", getCacheDir());
            FileOutputStream fos = new FileOutputStream(tempFile);
            
            // 写入大量数据
            byte[] buffer = new byte[1024];
            new Random().nextBytes(buffer);
            
            for (int i = 0; i < 5000; i++) {
                fos.write(buffer);
                fos.flush();
                
                // 每写入一段数据就执行同步刷新，增加IO操作耗时
                if (i % 100 == 0) {
                    logMessage("已写入 " + (i * buffer.length / 1024) + " KB 数据...");
                }
            }
            
            fos.close();
            tempFile.delete();
            
        } catch (IOException e) {
            logMessage("IO操作异常: " + e.getMessage());
        }
        
        logMessage("IO阻塞操作完成，如果看到此消息，说明ANR对话框被忽略或等待");
    }
    
    /**
     * 引发复杂计算阻塞导致的ANR
     * 在主线程中执行复杂的计算任务
     */
    private void triggerComplexCalculationANR() {
        logMessage("主线程即将执行复杂计算，这将导致ANR...");
        
        long startTime = System.currentTimeMillis();
        
        // 计算大量斐波那契数列
        int n = 45; // 足够大的数，使计算耗时超过5秒
        logMessage("计算第 " + n + " 个斐波那契数...");
        long result = calculateFibonacci(n);
        
        long endTime = System.currentTimeMillis();
        logMessage("计算结果: " + result);
        logMessage("计算耗时: " + (endTime - startTime) + " 毫秒");
        logMessage("复杂计算完成，如果看到此消息，说明ANR对话框被忽略或等待");
    }
    
    /**
     * 计算斐波那契数列的第n个数
     * 使用递归实现，效率较低，适合用于产生耗时计算
     */
    private long calculateFibonacci(int n) {
        if (n <= 0) return 0;
        if (n == 1) return 1;
        return calculateFibonacci(n - 1) + calculateFibonacci(n - 2);
    }
    
    /**
     * 记录日志信息到界面
     */
    private void logMessage(String message) {
        Log.d(TAG, message);
        
        runOnUiThread(() -> {
            String currentText = tvLogger.getText().toString();
            String newText = currentText + "\n" + message;
            tvLogger.setText(newText);
            
            // 滚动到底部
            svLogger.post(() -> svLogger.fullScroll(View.FOCUS_DOWN));
        });
    }
} 